﻿namespace EFS.RC.CC.Applications.EndPoints
{
	/// <summary>
	/// Manage our list of list
	/// </summary>
	internal class Registrar : EFS.Common.ISelfDescriptor
	{
		#region Composition

		/// <summary>
		/// Presences list
		/// </summary>
		private EFS.RC.CC.Presences.EndPoints.Registrar officeServicePresencesRegistrar = null;

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		public Registrar()
		{
			// make presences registrar
			officeServicePresencesRegistrar = new EFS.RC.CC.Presences.EndPoints.Registrar();

			// Load depoyment
			LoadDeployment();
		}

		#endregion

		#region Usage

		/// <summary>
		/// Describe this object
		/// </summary>
		/// <returns></returns>
		public System.String Describe()
		{
			return "EFS.RC.CC.Applications.EndPoints.Registrar";
		}

		/// <summary>
		/// Presences
		/// </summary>
		public EFS.RC.CC.Presences.EndPoints.Registrar OficeServicePresencesRegistrar
		{
			get { return officeServicePresencesRegistrar; }
		}

		/// <summary>
		/// Try start on registered presence
		/// </summary>
		/// <param name="applicationEndpointSettings"></param>
		/// <returns></returns>
		public EFS.Common.Async.AsyncProcess TryStartDiscoveredEndPoint(Microsoft.Rtc.Collaboration.ApplicationEndpointSettings applicationEndpointSettings)
		{
			try
			{
				// log
				EFS.EventLog.Log.LogInfo(System.String.Format("Add Discovered Application End Point {0}", applicationEndpointSettings.OwnerUri), this);

				// check
				EFS.Common.Verify.Reference(applicationEndpointSettings, "applicationEndpointSettings");

				// check if not already added
				EFS.RC.CC.Presences.EndPoints.OfficeService.Customer customerOfficeServiceEndPointPresence = officeServicePresencesRegistrar.GetCustomerOfficeServicePresence(applicationEndpointSettings.OwnerPhoneUri);

				// check is we find it as customer end point
				if (null != customerOfficeServiceEndPointPresence)
				{
					// start
					return customerOfficeServiceEndPointPresence.StartApplicationEndPoint(applicationEndpointSettings);
				}
				else
				{
					// check if is office end point
					if (EFS.RC.Common.Utilities.SipUriCompare(officeServicePresencesRegistrar.OperatorOfficeServiceEndPointPresence.PresenceEndPointDeployment.URI, applicationEndpointSettings.OwnerUri))
					{
						return officeServicePresencesRegistrar.OperatorOfficeServiceEndPointPresence.StartApplicationEndPoint(applicationEndpointSettings);
					}

					// check if is DirectDial end point
					if (EFS.RC.Common.Utilities.SipUriCompare(officeServicePresencesRegistrar.DirectDialOfficeServiceEndPointPresence.PresenceEndPointDeployment.URI, applicationEndpointSettings.OwnerUri))
					{
						return officeServicePresencesRegistrar.DirectDialOfficeServiceEndPointPresence.StartApplicationEndPoint(applicationEndpointSettings);
					}
				}
			}
			catch (System.Exception ex)
			{
				EFS.EventLog.Log.LogException(ex, this);
			}

			// unknown end point
			return null;
		}

		/// <summary>
		/// Shut down all end points
		/// </summary>
		/// <param name="ownerUri"></param>
		public System.Collections.Generic.List<EFS.Common.Async.AsyncProcess> ShutdownAllEndPoints()
		{
			// log
			EFS.EventLog.Log.LogInfo("ShutdownAll", this);

			// list for processes
			System.Collections.Generic.List<EFS.Common.Async.AsyncProcess> asyncProcesses = new System.Collections.Generic.List<EFS.Common.Async.AsyncProcess>();

			// all end point presences
			System.Collections.Generic.List<EFS.RC.CC.Presences.EndPoints.OfficeService.Customer> customersOfficeServiceEndPointPresenceList = officeServicePresencesRegistrar.UnRegisterAllCustomerOfficeServicePresences();

			// each customer end point presence
			foreach (EFS.RC.CC.Presences.EndPoints.OfficeService.Customer customersOfficeServiceEndPointPresence in customersOfficeServiceEndPointPresenceList)
			{
				// try stop
				EFS.Common.Async.AsyncProcess asyncProcess = customersOfficeServiceEndPointPresence.TryStopApplicationEndPoint();
				if (null != asyncProcess)
				{
					asyncProcesses.Add(asyncProcess);
				}
			}

			// operators end point presence
			EFS.RC.CC.Presences.EndPoints.OfficeService.Operator operatorsOfficeServiceEndPointPresence = officeServicePresencesRegistrar.UnRegisterOperatorOfficeServicePresence();
			if (null != operatorsOfficeServiceEndPointPresence)
			{
				// try stop
				EFS.Common.Async.AsyncProcess asyncProcess = operatorsOfficeServiceEndPointPresence.TryStopApplicationEndPoint();
				if (null != asyncProcess)
				{
					asyncProcesses.Add(asyncProcess);
				}
			}

			// operators end point presence
			EFS.RC.CC.Presences.EndPoints.OfficeService.DirectDial directDialOfficeServiceEndPointPresence = officeServicePresencesRegistrar.UnRegisterDirectDialOfficeServicePresence();
			if (null != directDialOfficeServiceEndPointPresence)
			{
				// try stop
				EFS.Common.Async.AsyncProcess asyncProcess = directDialOfficeServiceEndPointPresence.TryStopApplicationEndPoint();
				if (null != asyncProcess)
				{
					asyncProcesses.Add(asyncProcess);
				}
			}

			// return list
			return asyncProcesses;
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Load deployment
		/// </summary>
		private void LoadDeployment()
		{
			/* Office */

			// get office end point deployment
			EFS.RC.CC.Deployment.Entities.EndPoints.Office[] officeEndPointDeployments = EFS.RC.CC.Deployment.Tables.Tools.OfficeEndPoints.GetAll();

			// check
			EFS.Common.Verify.Reference(officeEndPointDeployments, "officeEndPointDeployments");
			EFS.Common.Verify.Condition(officeEndPointDeployments.Length == 1, "One Office EndPoint");

			// register
			EFS.RC.CC.Presences.EndPoints.OfficeService.Operator operatorOfficeServiceEndPointPresence = officeServicePresencesRegistrar.RegisterOfficeEndPointDeployment(officeEndPointDeployments[0]);

			// check
			EFS.Common.Verify.Reference(operatorOfficeServiceEndPointPresence, "operatorOfficeServiceEndPointPresence");

			/* Direct Dial */

			// register
			EFS.RC.CC.Presences.EndPoints.OfficeService.DirectDial directDialOfficeServiceEndPointPresence = officeServicePresencesRegistrar.RegisterDirectDialEndPointDeployment(
				new EFS.RC.CC.Config.DirectDialDeployment());

			/* Customers */

			// get end point deployment, try customer
			EFS.RC.CC.Deployment.Entities.EndPoints.Customer[] customerEndPointDeployments = EFS.RC.CC.Deployment.Tables.Tools.CustomerEndPoints.GetAll();

			// check
			EFS.Common.Verify.Reference(customerEndPointDeployments, "customerEndPointDeployments");

			// register
			foreach (EFS.RC.CC.Deployment.Entities.EndPoints.Customer customerEndPointDeployment in customerEndPointDeployments)
			{
				// register
				EFS.RC.CC.Presences.EndPoints.OfficeService.Customer customerOfficeServiceEndPointPresence = officeServicePresencesRegistrar.RegisterCustomerEndPointDeployment(customerEndPointDeployment);

				// check
				EFS.Common.Verify.Reference(customerOfficeServiceEndPointPresence, "customerOfficeServiceEndPointPresence");
			}
		}

		#endregion
	}
}
